#include <iostream>
#include <vector>
#include <set>
#include <sw/redis++/redis++.h>

#include "util.hpp"

void test1(sw::redis::Redis& redis)
{
    std::cout << "sadd 和 smembers" << std::endl;
    redis.flushall();
    redis.sadd("key", "111");

    redis.sadd("key", {"222", "333"});
    
    std::set<std::string> elems = {
        "444", "555", "666"
    };
    redis.sadd("key", elems.begin(), elems.end());

    std::vector<std::string> results;
    // std::set<std::string> results;
    // auto it = std::back_inserter<std::vector<std::string>>(results);

    // 对于 back_inserter 这种插入迭代器是会调用 push_back 这种操作的
    // 而 set 很显然没有这种操作
    // 所以需要使用更加普遍的方法 inserter, 指定迭代器
    // auto it = std::inserter<std::set<std::string>>(results, results.end());

    // 对于 vector 来说 inserter 也是可行的
    auto it = std::inserter<std::vector<std::string>>(results, results.end());

    redis.smembers("key", it);

    printContainer(results);
}

void test2(sw::redis::Redis& redis)
{
    std::cout << "sismember" << std::endl;
    redis.flushall();

    redis.sadd("key", {"111", "222", "333", "444"});
    bool result = redis.sismember("key", "111");
    std::cout << "result: " << result << std::endl;

    result = redis.sismember("key", "555");
    std::cout << "result: " << result << std::endl;
}

void test3(sw::redis::Redis& redis)
{
    std::cout << "scard" << std::endl;
    redis.flushall();

    long long len = redis.sadd("key", {"111", "222", "333", "444"});
    long long result = redis.scard("key");

    std::cout << "len: " << len << std::endl;
    std::cout << "result: " << result << std::endl;
}

void test4(sw::redis::Redis& redis)
{
    std::cout << "spop" << std::endl;
    redis.flushall();

    redis.sadd("key", {"111", "222", "333", "444", "555"});

    // 第一种方法, 只随机删除一个元素
    // sw::redis::OptionalString result = redis.spop("key");

    // if (result)
    // {
    //     std::cout << "result: " << result.value() << std::endl;
    // }

    // 第二种方法, 随机删除多个元素
    std::set<std::string> results;
    auto it = std::inserter<std::set<std::string>>(results, results.end());
    redis.spop("key", 3, it);

    printContainer(results);
}

void test5(sw::redis::Redis& redis)
{
    std::cout << "sinter" << std::endl;
    redis.flushall();

    redis.sadd("key1", {"111", "222", "333"});
    redis.sadd("key2", {"222", "333", "444"});

    std::set<std::string> results;
    auto it = std::inserter<std::set<std::string>>(results, results.end());
    redis.sinter({"key1", "key2"}, it);

    printContainer(results);
}

void test6(sw::redis::Redis& redis)
{
    std::cout << "sinterstore" << std::endl;
    redis.flushall();

    redis.sadd("key1", {"111", "222", "333"});
    redis.sadd("key2", {"222", "333", "444"});

    redis.sinterstore("key3", {"key1", "key2"});

    std::set<std::string> results;
    auto it = std::inserter<std::set<std::string>>(results, results.end());
    redis.smembers("key3", it);

    printContainer(results);
}

int main()
{
    sw::redis::Redis redis("tcp://127.0.0.1:6379");

    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    // test5(redis);
    test6(redis);

    return 0;
}